package com.bbcare.comm;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @Title: 先进先出队列
 * 
 * @author hutao
 * @version 2.0
 */
public class FifoMsgQueue<T> {
    private static int DEFAULT_CAPABILITY = 1000;
    private int capability;
    private LinkedList<T> msgQueue = new LinkedList<T>();
    private Object lock = new Object();

    /**
     * 默认的构造方法，其生成的队列的容量大小为默认的1000
     */
    public FifoMsgQueue() {
        this.capability = DEFAULT_CAPABILITY;
    }

    /**
     * 生成指定容量大小的队列
     * 
     * @param capability
     *            队列容量大小
     */
    public FifoMsgQueue(int capability) {
        this.capability = capability;
    }

    /**
     * 判断队列是否已满
     * 
     * @return
     */
    public synchronized boolean isFull() {
        return (msgQueue.size() == capability ? true : false);
    }

    /**
     * 返回队列的容量大小
     * 
     * @return
     */
    public synchronized int capability() {
        return capability;
    }

    /**
     * 返回当前队列大小
     * 
     * @return
     */
    public synchronized int size() {
        return msgQueue.size();
    }

    /**
     * 返回当前队列是否为空
     * 
     * @return
     */
    public synchronized boolean isEmpty() {
        return (msgQueue.size() <= 0 ? true : false);
    }

    /**
     * 将指定内容元素message放入队列中
     * 
     * @param message
     *            指定放入队列中的内容元素
     */
    public void push(T message) {
        synchronized (lock) {
            if (isFull()) {
                try {
                    // System.out.println("队列已满，有空位再插入[" + message + "]");
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            msgQueue.addLast(message);
        }
    }

    /**
     * 取出队列中第一个内容元素
     * 
     * @return 队列中第一个内容元素
     */
    public T pop() {
        synchronized (lock) {
            T message = null;
            if (!isEmpty()) {
                message = (T) msgQueue.removeFirst();
                lock.notifyAll();
            }
            return message;
        }
    }

    /**
     * 取出队列中指定个数的内容元素
     * 
     * @param num
     *            取出队列中的内容元素个数
     * @return
     */
    public List<T> pop(int num) {
        synchronized (lock) {
            LinkedList<T> messages = new LinkedList<T>();
            for (int i = 0; i < num; i++) {
                if (!isEmpty()) {
                    messages.addLast(this.pop());
                } else {
                    break;
                }
            }
            lock.notifyAll();
            return messages;
        }
    }

    /**
     * 返回指定队列索引处的内容元素
     * 
     * @param index
     *            队列内容元素索引
     * @return 指定索引处的内容元素
     */
    public synchronized T get(int index) {
        T message = null;
        if (isEmpty()) {
            message = (T) msgQueue.get(index);
        }
        return message;
    }

    /**
     * 移除队列指定索引处的内容元素
     * 
     * @param index
     *            队列内容元素索引
     * @return 移除的内容元素
     */
    public T remove(int index) {
        synchronized (lock) {
            T message = null;
            if (!isEmpty()) {
                message = (T) msgQueue.remove(index);
                lock.notifyAll();
            }
            return message;
        }
    }

    /**
     * 获取队列迭代器
     * 
     * @return 队列迭代器
     */
    public synchronized Iterator<T> iterator() {
        return msgQueue.iterator();
    }

    /**
     * 获取队列迭代器
     * 
     * @return 队列迭代器
     */
    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        Iterator<?> it = this.iterator();
        while (it.hasNext()) {
            str.append("\n");
            str.append(it.next().toString());
        }
        return str.toString();
    }

}
